package com.wangc.commons.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wangc.commons.utils.CommonsUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: 日志
 * @ClassName:WebLogAspect
 * @description: web切面
 * @author: GYB
 * @create: 2020-04-27 09:29
 **/
@Slf4j
@Aspect
@Component
public class WebLogAspect {
    @Pointcut("(execution (* com.wangc..controller..*(..)))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Exception {
        try {
            // 接收到请求，记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes();
            if (null == attributes) {
                return;
            }
            HttpServletRequest request = attributes.getRequest();
            String uri = request.getRequestURI();
            String remoteAdd = CommonsUtil.getRemoteAddress(request);

            StringBuilder sb = new StringBuilder(256);
            sb.append("mark_start|").append(uri).append("|");
            List<Object> list = new ArrayList<>();
            Object[] objs = joinPoint.getArgs();
            for (Object obj : objs) {
                if (obj instanceof MultipartFile || obj instanceof String || null == obj
                        || obj instanceof HttpServletRequest || obj instanceof HttpServletResponse) {
                    continue;
                }
                list.add(obj);
            }
            JSONArray requestParam = JSONArray.parseArray(JSON.toJSONString(list));
            if (null != requestParam && requestParam.size() > 0) {
                Object obj = requestParam.get(0);
                if (obj instanceof JSONObject) {
                    JSONObject requestOneParam = (JSONObject) obj;
                    requestParam.remove(0);
                    requestParam.add(requestOneParam);
                }

                sb.append(requestParam.toJSONString());
            }

            sb.append("|").append(remoteAdd);

            // 记录请求内容
            log.info(sb.toString());
        } catch (Exception ex) {
            log.error("mark_start|operator request log fail doBefore()", ex);
        }
    }

    @AfterReturning(pointcut = "webLog()", returning = "res")
    public void doAfterReturning(JoinPoint joinPoint, Object res) throws Exception {
        // 处理完请求，返回内容
        try {
            log.info("mark_end|" + JSONObject.toJSONString(res));

            printTimeConsuming();// 打印耗时
        } catch (Exception ex) {
            log.error("mark_end|operator request log fail doAfterReturning()", ex);
        }
    }

    /**
     * 打印耗时
     */
    private void printTimeConsuming() {
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null != attributes) {
            HttpServletRequest request = attributes.getRequest();

            log.info("afterCompletion url:{}, spendTime: {}", request.getRequestURI(),
                    (System.currentTimeMillis() - (Long) request.getAttribute("startTime")));
        }
    }
}
